stm32读写SD卡(SPI模式) 您所在的位置:网站首页 sd卡 电路 stm32读写SD卡(SPI模式)

stm32读写SD卡(SPI模式)

2024-06-24 03:57| 来源: 网络整理| 查看: 265

目录

一、SD卡简介

二、源码下载

三、移植条件

1、芯片参数

2、硬件连接

四、驱动代码

1、依赖宏如下

2、驱动代码实现

3、测试代码

4、运行截图

一、SD卡简介

SD卡有SD驱动模式和SPI驱动模式,本例中使用SPI模式驱动SD卡。

二、源码下载

https://download.csdn.net/download/qq_30095023/88014550

三、移植条件 1、芯片参数

芯片类型:STM32F103VET6。

flash大小为512KB,RAM大小 64KB。

2、硬件连接

本例使用TFT屏幕上的SD卡插口,测试所用SD卡容量大小为4GB。

 SD_CS、SPI_MOSI、SPI_MISO、SPI_CLK 与单片机连接。note:请确保屏幕电源连接正常。

如上图,红色框框所标记区域为TFT屏幕SD卡的SPI接口,将此接口与STM32单片机的SPI所对应的IO连接。

四、驱动代码

note: u8 、u16、u32等为自定义数据类型,编译报错请按需修改。LOG_XX为日志打印,请按需替换。

1、依赖宏如下

定义一些操作SD卡的命令和SD卡的类型。

//CMD定义 #define CMD0 0//卡复位 #define CMD1 1 #define CMD8 8//命令8 ,SEND_IF_COND #define CMD9 9//命令9 ,读CSD数据 #define CMD10 10//命令10,读CID数据 #define CMD12 12//命令12,停止数据传输 #define CMD16 16//命令16,设置SectorSize 应返回0x00 #define CMD17 17//命令17,读sector #define CMD18 18//命令18,读Multi sector #define CMD23 23//命令23,设置多sector写入前预先擦除N个block #define CMD24 24//命令24,写sector #define CMD25 25//命令25,写Multi sector #define CMD41 41//命令41,应返回0x00 #define CMD55 55//命令55,应返回0x01 #define CMD58 58//命令58,读OCR信息 #define CMD59 59//命令59,使能/禁止CRC,应返回0x00 //SD卡类型 #define ERR 0x00 #define MMC 0x01 #define V1 0x02 #define V2 0x04 #define V2HC 0x06 2、驱动代码实现

1)、ENTER_SD_BLOCK_SIZE定义SD卡的物理扇区大小为512Byte。

2)、函数SPI_Enable_T用来使能SPI接口,在SDinit的时候需要调用。

3)、函数inline u8 SPI_WriteByte_T用来单片机通过SPI读写SD卡,这里使用内联方式,减少函数调用过程中时间代价,有效提高SD卡的读写速率。关于inline关键字的详细用法请参考:

C语言基础知识--inline(内联)关键字_BIN-XYB的博客-CSDN博客

4)、 函数b_sd_read_write_byte用来读写数据。

5)、函数b_sd_send_cmd用来发送指令给SD卡。

6)、函数b_sd_read_data用来从SD卡读取指定长度的数据。

7)、函数b_sd_send_block_data用来向SD卡写入数据。

8)、函数b_sd_set_speed用来配置SPI通信速度。

9)、函数b_sd_init用来初始化SD卡,需要在使用SD卡前调用一次。

10)、函数b_sd_get_cid用来查询SD卡的CID。

11)、函数b_sd_get_csd用来查询SD卡的CSD。

12)、函数b_sd_read_sector用来读扇区数据,该接口一般用于FatFs文件系统。

13)、函数b_sd_write_sector用来写扇区数据,该接口一般用于FatFs文件系统。

FatFs文件系统移植请参考:FatFs移植到STM32(SD卡)_BIN-XYB的博客-CSDN博客

14)、函数b_sd_get_sector_number用来查询SD卡的扇区数量。

15)、函数b_sd_sync_data用来保存SD卡的数据。

完整源码如下:

#define ENTER_SD_BLOCK_SIZE (512) #define ENTER_SD_SECTOR_SIZE (ENTER_SD_BLOCK_SIZE) #define GPIO_TYPE GPIOD //GPIO组类型 #define SD_CS SD_CS_Pin//片选引脚PD8 #define SPI hspi2 //spi设备 #define SD_CS_DISABLE() GPIO_TYPE->BSRR=SD_CS//GPIO置位(拉高) #define SD_CS_ENABLE() GPIO_TYPE->BRR=SD_CS//GPIO复位(拉低) static u8 SPI_Enable_T(SPI_HandleTypeDef *hspi) { if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) { __HAL_SPI_ENABLE(hspi); } return 0; } static inline u8 SPI_WriteByte_T(SPI_HandleTypeDef* hspi,u8 Byte) { while((hspi->Instance->SR&SPI_FLAG_TXE)==RESET);//等待发送区空 hspi->Instance->DR=Byte;//发送一个byte while((hspi->Instance->SR&SPI_FLAG_RXNE)==RESET);//等待接收完一个byte return hspi->Instance->DR;//返回收到的数据 } #define SPI_WriteByte(spi_x, data) SPI_WriteByte_T(&spi_x, data) #define SPI_Enable(spi_x) SPI_Enable_T(&spi_x) u8 b_sd_read_write_byte(u8 tx_data) { u8 rx_data = SPI_WriteByte(SPI, tx_data); return rx_data; } static int b_sd_send_cmd(u8 cmd,u32 arg, u8 crc) { u8 r1; u8 retry; SD_CS_DISABLE(); b_sd_read_write_byte(0XFF); SD_CS_ENABLE(); do { retry = b_sd_read_write_byte(0XFF); }while(retry!=0xFF); b_sd_read_write_byte(cmd | 0x40); b_sd_read_write_byte(arg >> 24); b_sd_read_write_byte(arg >> 16); b_sd_read_write_byte(arg >> 8); b_sd_read_write_byte(arg); b_sd_read_write_byte(crc); if(cmd == CMD12) { b_sd_read_write_byte(0XFF); } do { r1 = b_sd_read_write_byte(0xFF); }while(r1 & 0X80); return r1; } static u8 sd_type = 0; static u8 b_sd_read_data(u8 *data, u16 len) { u8 r1 = 0; SD_CS_ENABLE(); do { r1 = b_sd_read_write_byte(0xFF); }while(r1 != 0xFE); while(len--) { *data = b_sd_read_write_byte(0xFF); data++; } b_sd_read_write_byte(0xFF); b_sd_read_write_byte(0xFF); return 0; } static u8 b_sd_send_block_data(u8* data, u8 cmd) { u16 t; u8 r1; do{ r1 = b_sd_read_write_byte(0xFF); }while(r1 != 0xFF); b_sd_read_write_byte(cmd); if(cmd != 0XFD)//不是结束指令 { for(t = 0; t < ENTER_SD_BLOCK_SIZE; t++) { b_sd_read_write_byte(data[t]);//提高速度,减少函数传参时间 } b_sd_read_write_byte(0xFF);//忽略crc b_sd_read_write_byte(0xFF); t = b_sd_read_write_byte(0xFF);//接收响应 if((t & 0x1F) != 0x05) { return 2;//响应错误 } } return 0;//写入成功 } inline void b_sd_set_speed(u32 speed) { hspi2.Init.BaudRatePrescaler = speed; } u8 b_sd_init(void) { u8 r1; u8 buff[6] = {0}; u16 retry; u8 i; SPI_Enable(SPI); b_sd_set_speed(SPI_BAUDRATEPRESCALER_256); SD_CS_DISABLE(); for(retry = 0; retry < 10; retry++) { b_sd_read_write_byte(0XFF); } do//SD卡进入IDLE状态 { r1 = b_sd_send_cmd(CMD0 ,0, 0x95); }while(r1 != 0x01); //查看SD卡的类型 sd_type = 0; r1 = b_sd_send_cmd(CMD8, 0x1AA, 0x87); if(r1 == 0x01) { for(i = 0; i < 4; i++) { buff[i] = b_sd_read_write_byte(0XFF);//Get trailing return value of R7 resp } if(buff[2] == 0X01 && buff[3] == 0XAA)//卡是否支持2.7~3.6V { retry = 0XFFFE; do { b_sd_send_cmd(CMD55, 0, 0X01);//发送CMD55 r1 = b_sd_send_cmd(CMD41, 0x40000000, 0X01);//发送CMD41 }while(r1 && retry--); if(retry && b_sd_send_cmd(CMD58, 0, 0X01) == 0)//鉴别SD2.0卡版本开始 { for(i = 0; i < 4; i++) { buff[i] = b_sd_read_write_byte(0XFF);//得到OCR值 } if(buff[0] & 0x40) { sd_type = V2HC; }else { sd_type = V2; } } } else { b_sd_send_cmd(CMD55, 0, 0X01);//发送CMD55 r1 = b_sd_send_cmd(CMD41, 0, 0X01);//发送CMD41 if(r1


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有